package net.vsame.url2sql.url.impl;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import net.vsame.url2sql.helper.SqlHelper;
import net.vsame.url2sql.helper.Url2SqlContext;
import net.vsame.url2sql.helper.WebHelper;
import net.vsame.url2sql.url.Interceptor;
import net.vsame.url2sql.url.impl.UrlMapping.Chain;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

/**
 * Action 执行拦截器
 * @author <a href="mailto:gaollg@sina.com">Gaollg</a>
 * @data 2013-5-6
 *
 */
public class ActionInterceptor implements Interceptor{
	
	private static Invocable jsFunction = null;
	
	//================================ 加载js ==========================
	static {
		resetJsInvocable();
	}
	
	private static void loadResource(ScriptEngine engine, String resource){
		// Run InvScript.js
		Reader scriptReader = new InputStreamReader(ActionInterceptor.class.getResourceAsStream(resource), Charset.forName("utf-8"));
		try {
			engine.eval(scriptReader);
		}catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				scriptReader.close();
			} catch (IOException e) {
			}
		}
	}
	
	public static void resetJsInvocable() {
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("JavaScript");
		loadResource(engine, "/core.js");
		if (engine instanceof Invocable) {
			jsFunction = (Invocable) engine;
		}else{
			throw new RuntimeException("not suppont!");
		}
	}
	
	/**
	 * 调用方法
	 * @param method
	 * @return
	 */
	public static Object invokeMethod(Method method){
		try {
			Object o = method.getDeclaringClass().newInstance();
			return method.invoke(o);
		} catch (Exception e) {
			throw new RuntimeException(e.getCause());
		}
	}
	
	@Override
	public void init(UrlMapping urlMapping) {
	}
	
	@Override
	public void invoke(Chain chain) {
		//调用Action
		Url2SqlContext c =  WebHelper.getContext();
		UrlConfig u = c.getUrlConfig();
		Method m = u.getMethod();
		if(m != null){
			invokeMethod(m);
		}else {
			executeJs();
		}
	}
	
	
	@Override
	public void destroy() {
		
	}
	
	public void executeJs(){
		List<String> errors = new ArrayList<String>();
		try {
			Url2SqlContext c = WebHelper.getContext();
			UrlConfig urlConfig = c.getUrlConfig();
			String json = "var vars="+ JSON.toJSONString(urlConfig.getVars(), SerializerFeature.WriteDateUseDateFormat)+";";
			jsFunction.invokeFunction("execute", json + urlConfig.getJs(), c, errors);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		if(!errors.isEmpty()){
			throw new RuntimeException(errors.get(0));
		}
	}
	
	public static void main(String[] args) {
		Url2SqlContext c = WebHelper.getContext();
		UrlConfig urlConfig = new UrlConfig();
		c.setUrlConfig(urlConfig);
		c.setParams(new HashMap<String, String[]>());
		urlConfig.setJs("println('=========================');" +
				"context.put('a', 'b');" +
				"context.put('page', SQL.page('select *', 'from student', '1'));" +
				"context.put('page', SQL.alltables());" +
				"context.put('queryAllResult', SqlHelper.query('select * from student where id in(?)', [4,2,3]));");
		
		new ActionInterceptor().executeJs();
		System.out.println(c.getDatas());
		SqlHelper.class.getMethods();
	}
	
}
